import { Body, Inject, Provide } from '@midwayjs/core';
import { BaseService, CoolCommException, CoolTag, TagTypes } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { DeviceDeviceEntity } from '../entity/device';
import { PluginService } from '../../plugin/service/info';
import axios from 'axios';
import { DeviceAlertEntity } from '../entity/alert';
import * as CryptoJS from 'crypto-js';
import { randomUUID } from '@midwayjs/core/dist/util/uuid';

/**
 * 设备信息
 */
@Provide()
export class DeviceDeviceService extends BaseService {
  @InjectEntityModel(DeviceDeviceEntity)
  deviceDeviceEntity: Repository<DeviceDeviceEntity>;

  @InjectEntityModel(DeviceAlertEntity)
  deviceAlertEntity: Repository<DeviceAlertEntity>;

  @Inject()
  pluginService: PluginService;

  @Inject()
  ctx;

  // 获取设备二维码
  async getDeviceQrCode(params) {
    // 获取插件实例
    const instance = await this.pluginService.getInstance('wx');

    // 获得公众号实例
    const MiniAppAccount = await instance.MiniApp();

    // 获取公众号的 access token
    const token = await MiniAppAccount.getAccessToken();

    const access_token = await token.getToken();

    const result = await axios.post(
      'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' +
      access_token,
      {
        ...params,
      },
      {
        responseType: 'arraybuffer',
      }
    );

    const base64Data = Buffer.from(result.data).toString('base64');
    result.data = `data:image/png;base64,${base64Data}`;

    return result.data;
  }

  // 绑定设备
  async bind(param: any) {
    // 获取当前用户信息
    const userId = this.ctx.user.id;

    const { imei } = param;

    // 先通过设备ID查询设备信息
    const device = await this.deviceDeviceEntity.findOneBy({
      imei: imei,
    });

    // 设备不存在
    if (!device) {
      throw new CoolCommException('设备不存在');
    }

    // 如果设备存在，判断是否绑定过
    if (device.userId) {
      throw new CoolCommException('设备已绑定');
    }

    // 如果设备没有绑定过，则绑定
    return await this.deviceDeviceEntity.update(
      {
        imei: imei,
      },
      {
        userId,
      }
    );
  }

  // 获取设备列表
  async getList(params: any) {
    // 获取当前用户信息
    const userId = this.ctx.user.id;
    const find = this.deviceDeviceEntity.createQueryBuilder();
    find.where('userId = :userId', { userId });
    return this.entityRenderPage(find, params);
  }
  /* 发送指令 */
  async sendCommand({ imei, command }: { imei: string; command: string }) {
    const device = await this.deviceDeviceEntity.findOneBy({ imei });
    if (!device) {
      throw new Error('设备不存在');
    }

    // // 获取插件实例
    const instance = await this.pluginService.getInstance('mqtt');

    instance.publish(
      `$thing/down/property/hqwkq123/${imei}/`,

      // `$thing/down/property/hqwkq123/`,
      JSON.stringify(command)
    );

    return true;
  }

  // 通过id查设备信息
  async getDeviceInfo(body: any) {
    const { id } = body;

    const device = await this.deviceDeviceEntity.findOneBy({ id: id });
    if (!device) {
      throw new Error('设备不存在');
    }

    return device;
  }

  // 预警配置
  async setAlertConfig(params: any) {
    // 通过params的id去新增获取修改配置
    return await this.deviceAlertEntity.update(
      {
        deviceId: params.deviceId,
      },
      {
        ...params
      }
    );
  }

  // 获取预警配置
  async getAlertConfig(params) {
    const _config = await this.deviceAlertEntity.findOneBy({
      deviceId: params.id,
    });

    // 如果没有找到配置，插入一条默认配置
    if (!_config) {
      return await this.deviceAlertEntity.save({
        deviceId: params.id,
        alertPhone: '',
        alertTimeStart: '',
        alertTimeEnd: '',
        lowTemperature: 0,
        highTemperature: 0,
        smsAlert: false,
        phoneAlert: false,
        wxAlert: false,
      });
    } else {
      return _config;
    }
  }

  // 发送短信
  @CoolTag(TagTypes.IGNORE_TOKEN)
  async sendSms(@Body() params) {
    // 发送
    const _res = await this.pluginService.invoke(
      'sms-tx',
      'send',
      ['13580078463'],
      [],
      {
        signName: '深圳海骐科技有限公司',
        template: '2532346'
      }
    );

    return _res;
  }

  // 获取天气预报
  // async getDeviceWeather(params) {

  //   // 云市场分配的密钥Id
  //   var secretId = "P7ogRBbDzN9H1xNm";
  //   // 云市场分配的密钥Key
  //   var secretKey = "BsGT4PUDJLGLbG4X3QhlqsMYl9GTdAtk";

  //   // 签名
  //   var datetime = (new Date()).toUTCString();
  //   var uuId = randomUUID();
  //   var signStr = "x-date: " + datetime;
  //   var sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA1(signStr, secretKey))
  //   var auth = '{"id": "' + secretId + '", "x-date": "' + datetime + '", "signature": "' + sign + '"}';

  //   // 请求
  //   const result = await axios.get(
  //     'https://ap-beijing.cloudmarket-apigw.com/service-iw45ygyx/adress',
  //     {
  //       params: {
  //         from: "1",
  //         lat: "23.129163",
  //         lng: "113.264435",
  //       },

  //       headers: {
  //         "Content-Type": "application/json",
  //         "request-id": uuId,
  //         "Authorization": auth
  //       }
  //     },

  //   );

  //   return result;

  // }
  // 获取天气预报
  // 获取天气预报
  async getDeviceWeather(params) {

    // 云市场分配的密钥Id
    var secretId = "ofBgUzNObtEielTC";
    // 云市场分配的密钥Key
    var secretKey = "bulWxO65ukhCsKTeST3Gi9Ih6A9TeDDY";

    // 签名
    var datetime = new Date().toUTCString(); // 使用标准UTC时间格式
    var uuId = randomUUID();
    var signStr = "x-date: " + datetime;
    var sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA1(signStr, secretKey));

    // 构建 Authorization 头部
    var authObj = {
      id: secretId,
      "x-date": datetime,
      signature: sign
    };

    var auth = JSON.stringify(authObj);

    // 请求
    const result = await axios.get(
      'https://ap-beijing.cloudmarket-apigw.com/service-iw45ygyx/adress',
      {
        params: {
          from: "1",
          lat: params?.lat,
          lng: params?.lng,
          // 是否需要当天每3/6/8小时一次的天气预报列表。1为需要，0为不需要。注意f1是3小时间隔，但f2到f7的间隔可能是6或8小时。
          need3HourForcast: 0,
          // 是否需要天气预警。1为需要，0为不需要
          needAlarm: 1,
          // 是否需要每小时数据的累积数组。由于本系统是半小时刷一次实时状态，因此实时数组最大长度为48。每天0点长度初始化为0. 1为需要 0为不
          needHourData: 1,
          needMoreDay: 1
        },
        headers: {
          "Content-Type": "application/json",
          "request-id": uuId,
          "Authorization": auth
        }
      },
    );


    // 只返回需要的数据，避免返回包含循环引用的整个响应对象
    return result.data
  }
}
